WebSocket 是一個即時更新的服務,所以如果你的應用程式規模很大,或是客戶數量很多,就可能會碰到處理大量訊息的問題。這邊分享幾個處理訊息的機制,希望能對各位有所幫助。
我們可以將多個訊息合併成一個批次進行處理,這樣能減少伺服器的負擔,也能提高系統效率。實作方式為,將在短時間內收到的多個消息合併成一個批次,然後一次性發送給伺服器。這樣可以減少網絡請求的次數,降低網絡延遲。
以下做一個簡單的聊天室例子,將十秒內收到的訊息一次傳給 WebSocket
const websocket = new WebSocket('wss://url');
let messageQueue = [];
const BATCH_INTERVAL = 10000; // 10秒
websocket.onopen = function() {
console.log('WebSocket 連接已建立');
};
websocket.onmessage = function(event) {
const messages = JSON.parse(event.data);
};
function sendMessage() {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value;
if (message) {
messageQueue.push({ content: message });
messageInput.value = '';
}
}
setInterval(() => {
if (messageQueue.length > 0) {
const batch = messageQueue.splice(0, messageQueue.length);
websocket.send(JSON.stringify(batch));
}
}, BATCH_INTERVAL);
在處理 WebSocket 的訊息時,可以使用 JavaScript 的非同步來避免阻塞主線程。
websocket.onmessage = async function(event) {
const messages = JSON.parse(event.data);
for (const message of messages) {
await processMessage(message);
}
};
async function processMessage(message) {
await new Promise(resolve => setTimeout(resolve, 100));
console.log('Processed message:', message);
}
在前一篇文章有提到要立即掌握 WebSocket 的連線其實有困難性,我們有先透過 ping / pong 這種雙向心跳機制在後端做底層網路層的偵測處理。那如果是前端,可以怎麼設計呢?
前端通常會用重連機制主動去重連 WebSocket,因為有時候可能是網路問題,只要重連個兩、三次就能正常。此外如果可以,也要記錄錯誤日誌並返回錯誤,讓 Server 協助排查,並告知使用者相關的錯誤應對方式。
以我為例,因為我們公司是後台系統,有時候需要瞭解客戶的操作以及當下碰到的問題,所以我請後端開發一隻錯誤日誌的 API,讓我能記錄如 WebSocket 連線錯誤時的訊息,並透過上述的非同步與批次處理,將錯誤日誌每隔一段時間發送到 API 利於排查。
async function processMessage(message) {
try {
await new Promise(resolve => setTimeout(resolve, 100));
console.log('處理的訊息:', message);
} catch (error) {
console.error('error', error);
}
}
不管是重新發送訊息或是重新連線,都能用相同的概念做處理,我們可以自訂重試的次數以及間隔時間
async function processMessageWithRetry(message, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
await processMessage(message);
return;
} catch (error) {
console.error(`嘗試第 ${i + 1} 次失敗:`, error);
await new Promise(resolve => setTimeout(resolve, (i + 1) * 1000));
}
}
console.error('全部的嘗試都失敗');
}
https://mukiwu.github.io/web-api-demo/websocket-msg.html
以上,有任何問題歡迎留言討論唷。